﻿using System;
using System.Collections.Generic;
using System.IO;

namespace ODM_Code.Code
{
    public class FlammapCode
    {
        private string dbfPath;
        private string inputPath;
        private string alternativePath;
        private Dictionary<int, firedata> scenarios;

        public FlammapCode(string dbfPath, string inputPath, string alternativePath)
        {
            this.dbfPath = dbfPath;
            this.inputPath = inputPath;
            this.alternativePath = alternativePath;
            scenarios = new Dictionary<int, firedata>();
        }

        public Dictionary<int, firedata> ParseScenarios()
        {
            string scenariosfile = alternativePath + "\\Scenarios.txt";
            if (File.Exists(scenariosfile))
            {
                StreamReader sr = new StreamReader(scenariosfile);
                scenarios.Clear();
                string line = sr.ReadLine();
                int count = 0;
                while (!sr.EndOfStream)
                {
                    line = sr.ReadLine();
                    if (line.Length > 1)
                    {
                        count += 1;
                        firedata fire = new firedata();
                        string[] spl = line.Split('\t');
                        fire.problem_id = spl[0];
                        fire.base_year = spl[1];
                        fire.disc_rate = spl[2];
                        fire.time_perds = spl[3];
                        fire.time_len = spl[4];
                        fire.clust_size = spl[5];
                        fire.windspd = spl[6];
                        fire.winddir = spl[7];
                        fire.foilmoist = spl[8];
                        fire.crownfuel = spl[9];
                        fire.groundfuel = spl[10];
                        fire.latitude = spl[11];
                        fire.gridunits = spl[12];
                        fire.foptions = spl[13];
                        fire.eunits = spl[14];
                        fire.sunits = spl[15];
                        fire.aunits = spl[16];
                        fire.cunits = spl[17];
                        fire.hunits = spl[18];
                        fire.bunits = spl[19];
                        fire.punits = spl[20];
                        fire.weight = spl[21];

                        scenarios.Add(count, fire);
                    }
                }
                sr.Close();
            }
            return scenarios;
        }

        public void WriteNewScenarios()
        {
            StreamWriter sw = new StreamWriter(alternativePath + "\\Scenarios.txt");
            sw.WriteLine("PROBLEM_ID\tBASE_YEAR\tDISC_RATE\tTIME_PERDS\tTIME_LEN\tCLUST_SIZE\tWNDSPD\tWNDDIR\tFOLMOIST\tCROWNFUEL\tGROUNDFUEL\tLATITUDE\tGRIDUNITS\tFOPTIONS\tEUNITS\tSUNITS\tAUNITS\tCUNITS\tHUNITS\tBUNITS\tPUNITS\tWEIGHT");

            for (int i = 0; i < scenarios.Count; i++)
            {
                firedata fire = scenarios[i + 1];
                string[] fireInfos = 
                {
                    fire.problem_id,
                    fire.base_year,
                    fire.disc_rate,
                    fire.time_perds,
                    fire.time_len,
                    fire.clust_size,
                    fire.windspd,
                    fire.winddir,
                    fire.foilmoist,
                    fire.crownfuel,
                    fire.groundfuel,
                    fire.latitude,
                    fire.gridunits,
                    fire.foptions,
                    fire.eunits,
                    fire.sunits,
                    fire.aunits,
                    fire.cunits,
                    fire.hunits,
                    fire.bunits,
                    fire.punits,
                    fire.weight
                };

                string line = "";
                for (int j = 0; j < fireInfos.Length; j++)
                {
                    string txt = fireInfos[j];

                    if (txt.Equals("") || txt == null)
                    {
                        line += "\t";
                        continue;
                    }
                    else if (j == 0)
                    {
                        line = txt;
                    }
                    else
                    {
                        line += "\t" + txt;
                    }
                }
                sw.WriteLine(line);
            }

            sw.Close();
        }

        public int AddNewFireScenario(firedata fire)
        {
            fire.base_year = "2012";
            fire.disc_rate = "0.04";
            fire.time_perds = "3";
            fire.time_len = "5";
            fire.clust_size = "50";
            fire.crownfuel = "1";
            fire.groundfuel = "0";
            fire.latitude = "39.0000";
            fire.gridunits = "0";
            fire.foptions = "0";
            fire.eunits = "0";
            fire.sunits = "0";
            fire.aunits = "2";
            fire.cunits = "1";
            fire.hunits = "1";
            fire.bunits = "1";
            fire.punits = "1";
            int newFireNum = scenarios.Count + 1;
            scenarios.Add(newFireNum, fire);
            this.ParseFMS(newFireNum);
            return newFireNum;
        }

        public void UpdateFireScenario(int fireNumber, firedata fire)
        {
            this.ParseFMS(fireNumber);
            scenarios[fireNumber] = fire;
        }

        public Dictionary<int, firedata> RemoveFireScenario(int fireNumber)
        {
            Dictionary<int, firedata> newList = new Dictionary<int, firedata>();
            int count = 0;
            for (int i = 1; i <= scenarios.Count; i++)
            {
                string inputini = alternativePath + "\\inputfile" + i.ToString() + ".ini";
                string inputasc = alternativePath + "\\inputfile" + i.ToString() + ".asc";

                if (i != fireNumber)
                {
                    count += 1;
                    newList[count] = scenarios[i];
                }
                if (i == fireNumber)
                {
                    File.Delete(inputini);
                    File.Delete(inputasc);
                }
                if (i > fireNumber)
                {
                    string tempini = alternativePath + "\\inputfile" + (i - 1).ToString() + ".ini";
                    string tempasc = alternativePath + "\\inputfile" + (i - 1).ToString() + ".asc";
                    File.Copy(inputini, tempini);
                    File.Copy(inputasc, tempasc);
                    File.Delete(inputini);
                    File.Delete(inputasc);
                }
            }
            scenarios = newList;

            return scenarios;
        }

        public void WriteInputFile(int fireNumber)
        {
            StreamWriter sw = new StreamWriter(alternativePath + "\\inputfile" + fireNumber.ToString() + ".asc");

            firedata fire = scenarios[fireNumber];
            int fmsCount = fire.fms.Count;

            sw.WriteLine("FUEL_MOISTURE_DATA: " + (fmsCount + 1).ToString());
            sw.WriteLine("0 0 0 0 0 0");
            for (int i = 0; i < fmsCount; i++)
            {
                sw.WriteLine(fire.fms[i]);
            }
            sw.WriteLine();

            sw.WriteLine("WIND_SPEED: " + fire.windspd);
            sw.WriteLine("WIND_DIRECTION: " + fire.winddir);
            sw.WriteLine("GRIDDED_WINDS_GENERATE: " + "No");
            sw.WriteLine("GRIDDED_WINDS_RESOLUTION: " + "200");
            sw.WriteLine("FOLIAR_MOISTURE_CONTENT: " + fire.foilmoist);
            sw.WriteLine("CROWN_FIRE_METHOD: " + "ScottReinhardt");
            sw.WriteLine("NUMBER_PROCESSORS: " + "4");
            sw.WriteLine("MTT_RESOLUTION: " + "90");
            sw.WriteLine("MTT_SIM_TIME: " + "0");
            sw.WriteLine("MTT_TRAVEL_PATH_INTERVAL: " + "500");
            sw.WriteLine("MTT_SPOT_PROBABILITY: " + "0.0");
            sw.WriteLine("MTT_IGNITION_FILE: " + fire.igniPath);
            sw.WriteLine("FLAMELENGTH: ");
            sw.WriteLine();
            sw.Close();
        }

        public void WriteInputFile(int fireNumber, bool overrideMTT)
        {

        }

        public void ParseIniFile(int fireNumber)
        {
            try
            {
                StreamReader sr = new StreamReader(alternativePath + "\\inputfile" + fireNumber.ToString() + ".ini");
                string line = "";
                string beg = "";
                string sub = "";

                firedata fire = scenarios[fireNumber];

                while (!sr.EndOfStream)
                {
                    line = sr.ReadLine();
                    beg = line.Substring(0, line.IndexOf(":"));
                    sub = line.Substring(line.IndexOf(":") + 1);

                    switch (beg)
                    {
                        case "FMS":
                            fire.fmsPath = sub;
                            break;
                        case "IGNITION":
                            fire.igniPath = sub;
                            break;
                        case "DESC":
                            fire.description = sub;
                            break;
                        case "WINDDIRGRID":
                            fire.gridWindDirPath = sub;
                            break;
                        case "WINDSPDGRID":
                            fire.gridWindSpeedPath = sub;
                            break;
                    }
                }

                sr.Close();
            }
            catch (FileNotFoundException flex)
            {
                System.Diagnostics.Trace.WriteLine(flex.Message);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message);
            }
        }

        public void WriteIniFile(int fireNumber, string pathToFMS, string pathToIgnition)
        {
            this.WriteIniFile(fireNumber, pathToFMS, pathToIgnition, null);
        }

        public void WriteIniFile(int fireNumber, string pathToFMS, string pathToIgnition, string description)
        {
            this.WriteIniFile(fireNumber, pathToFMS, pathToIgnition, description, null, null);
        }

        public void WriteIniFile(int fireNumber, string pathToFMS, string pathToIgnition, string description, string pathToWindDirGrid, string pathToWindSpeedGrid)
        {
            string iniPath = alternativePath + "\\inputfile" + fireNumber.ToString() + ".ini";

            StreamWriter sw = new StreamWriter(iniPath);
            sw.WriteLine("FMS:" + pathToFMS);
            sw.WriteLine("IGNITION:" + pathToIgnition);
            sw.WriteLine("DESC:" + description);
            sw.WriteLine("WINDDIRGRID:" + pathToWindDirGrid);
            sw.WriteLine("WINDSPDGRID:" + pathToWindSpeedGrid);
            sw.Close();
        }

        public void ParseFMS(int fireNumber)
        {
            try
            {
                firedata fire = scenarios[fireNumber];
                string pathToFMS = fire.fmsPath;
                List<string> fms = new List<string>();
                StreamReader sr = new StreamReader(pathToFMS);
                while (!sr.EndOfStream)
                {
                    fms.Add(sr.ReadLine());
                }
                fire.fms = fms;
            }
            catch (FileNotFoundException flex)
            {
                System.Diagnostics.Trace.WriteLine(flex.Message);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.Message);
            }
        }

        public int CountScenarios()
        {
            return scenarios.Count;
        }

        

        public class firedata
        {
            public string problem_id { get; set; }
            public string base_year { get; set; }
            public string disc_rate { get; set; }
            public string time_perds { get; set; }
            public string time_len { get; set; }
            public string clust_size { get; set; }
            public string windspd { get; set; }
            public string winddir { get; set; }
            public string foilmoist { get; set; }
            public string crownfuel { get; set; }
            public string groundfuel { get; set; }
            public string latitude { get; set; }
            public string gridunits { get; set; }
            public string foptions { get; set; }
            public string eunits { get; set; }
            public string sunits { get; set; }
            public string aunits { get; set; }
            public string cunits { get; set; }
            public string hunits { get; set; }
            public string bunits { get; set; }
            public string punits { get; set; }
            public string weight { get; set; }
            public string fmsPath { get; set; }
            public string igniPath { get; set; }
            public string description { get; set; }
            public string gridWindDirPath { get; set; }
            public string gridWindSpeedPath { get; set; }
            public List<string> fms { get; set; }
        }

        public class mttdata
        {
            public bool generateGriddedWinds { get; set; }
            public float griddedWindsResolution { get; set; }
            public string crownFireMethod { get; set; }
            public int numberProcs { get; set; }
            public float resolution { get; set; }
            public float simtime { get; set; }
            public float travelPathInterval { get; set; }
            public float spotProbability { get; set; }
        }
    }
}
